package com.xlhj.yucloud.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xlhj.yucloud.entity.SysMenuInfo;
import com.xlhj.yucloud.entity.enums.StatusEnum;
import com.xlhj.yucloud.mapper.SysMenuInfoMapper;
import com.xlhj.yucloud.service.SysMenuInfoService;
import com.xlhj.yucloud.web.model.MenuInfoReqDto;
import com.xlhj.yucloud.web.model.MetaMenu;
import com.xlhj.yucloud.web.model.RouterMenu;
import com.xlhj.yucloud.web.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * @author: liucaijing
 * @description: SysMenuInfoServiceImpl
 * @date: 2021/9/9 21:39
 */
@Service
public class SysMenuInfoServiceImpl extends ServiceImpl<SysMenuInfoMapper, SysMenuInfo> implements SysMenuInfoService {

    @Autowired
    private SysMenuInfoMapper menuInfoMapper;
    @Autowired
    private RedisService redisService;

    @Override
    public Set<String> getMenuPermsByUserId(Long userId) {
        List<String> permList = menuInfoMapper.getMenuPermsByUserId(userId);
        Set<String> permSet = new HashSet<>();
        permSet.addAll(permList);
        return permSet;
    }

    @Override
    public List<SysMenuInfo> selectMenuTreeByUserId(Long userId) {
        List<SysMenuInfo> menuInfoList = menuInfoMapper.selectMenuTreeByUserId(userId);
        return getChildPerms(menuInfoList, 0);
    }

    /**
     * 构建前端路由所需的菜单
     * @param menuInfos
     * @return
     */
    @Override
    public List<RouterMenu> buildMenus(List<SysMenuInfo> menuInfos) {
        List<RouterMenu> routerMenus = new LinkedList<>();
        for (SysMenuInfo menuInfo : menuInfos) {
            RouterMenu routerMenu = new RouterMenu();
            //routerMenu.setHidden(menuInfo.getVisible().intValue() == 1);
            routerMenu.setName(getRouteName(menuInfo));
            routerMenu.setPath(getRoutePath(menuInfo));
            routerMenu.setComponent(getComponent(menuInfo));
            routerMenu.setMeta(new MetaMenu(menuInfo.getMenuName(), menuInfo.getIcon()));
            List<SysMenuInfo> childMenus = menuInfo.getChildren();
            if (!childMenus.isEmpty() && childMenus.size() > 0 && "M".equals(menuInfo.getMenuType())) {
                routerMenu.setChildren(buildMenus(childMenus));
            }
            routerMenus.add(routerMenu);
        }
        return routerMenus;
    }

    @Override
    public List<SysMenuInfo> selectMenuInfoList(MenuInfoReqDto reqDto, Long userId) {
        List<SysMenuInfo> menuInfoList = null;
        if (userId.longValue() == 1) {
            LambdaQueryWrapper<SysMenuInfo> queryWrapper = new LambdaQueryWrapper<>();
            if (StringUtils.hasLength(reqDto.getMenuName())) {
                queryWrapper.like(SysMenuInfo::getMenuName, reqDto.getMenuName());
            }
            if (!ObjectUtils.isEmpty(reqDto.getStatus())) {
                queryWrapper.eq(SysMenuInfo::getStatus, reqDto.getStatus());
            }
            queryWrapper.orderByAsc(SysMenuInfo::getParentId);
            queryWrapper.orderByAsc(SysMenuInfo::getMenuSort);
            menuInfoList = menuInfoMapper.selectList(queryWrapper);
        } else {
            //menuInfoMapper.selectMenuInfoByUserId()
        }
        return menuInfoList;
    }

    @Override
    public Boolean checkMenuNameUnique(Long menuId, String menuName, Long parentId) {
        LambdaQueryWrapper<SysMenuInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenuInfo::getMenuName, menuName)
                .eq(SysMenuInfo::getParentId, parentId)
                .eq(SysMenuInfo::getStatus, StatusEnum.NORMAL.getCode());
        SysMenuInfo menuInfo = menuInfoMapper.selectOne(queryWrapper);
        if (!ObjectUtils.isEmpty(menuInfo) && StringUtils.hasLength(String.valueOf(menuId)) && menuId.longValue() != menuInfo.getId().longValue()) {
            return true;
        }
        return false;
    }

    /**
     * 获取路由名称
     * @param menuInfo
     * @return
     */
    private String getRouteName(SysMenuInfo menuInfo) {
        String routeName = StringUtils.capitalize(menuInfo.getPath());
        if (menuInfo.getParentId().longValue() == 0 && "C".equals(menuInfo.getMenuType())) {
            routeName = "";
        }
        return routeName;
    }

    /**
     * 获取路由地址
     * @param menuInfo
     * @return
     */
    private String getRoutePath(SysMenuInfo menuInfo) {
        String routePath = menuInfo.getPath();
        if (menuInfo.getParentId().longValue() == 0 && "M".equals(menuInfo.getMenuType())) {
            routePath = "/" + menuInfo.getPath();
        } else if (menuInfo.getParentId().longValue() == 0 && "C".equals(menuInfo.getMenuType())) {
            routePath = "/";
        }
        return routePath;
    }

    /**
     * 获取组件
     * @param menuInfo
     * @return
     */
    private String getComponent(SysMenuInfo menuInfo) {
        String component = "Layout";
        if (StringUtils.hasLength(menuInfo.getComponent())) {
            component = menuInfo.getComponent();
        }
        return component;
    }

    /**
     * 根据父节点ID获取子节点
     * @param menuInfoList
     * @param parentId
     * @return
     */
    private List<SysMenuInfo> getChildPerms(List<SysMenuInfo> menuInfoList, int parentId) {
        List<SysMenuInfo> menuInfos = new ArrayList<>();
        for (Iterator<SysMenuInfo> iterator = menuInfoList.iterator(); iterator.hasNext(); ) {
            SysMenuInfo menuInfo = iterator.next();
            if (menuInfo.getParentId() == parentId) {
                recursionFn(menuInfoList, menuInfo);
                menuInfos.add(menuInfo);
            }
        }
        return menuInfos;
    }

    /**
     * 递归获取菜单列表
     * @param menuInfoList
     * @param menuInfo
     */
    private void recursionFn(List<SysMenuInfo> menuInfoList, SysMenuInfo menuInfo) {
        List<SysMenuInfo> childList = getChildList(menuInfoList, menuInfo);
        menuInfo.setChildren(childList);
        for (SysMenuInfo childMenu : childList) {
            if (hasChild(menuInfoList, childMenu)) {
                recursionFn(menuInfoList, childMenu);
            }
        }
    }

    /**
     * 判断是否有子节点
     * @param menuInfoList
     * @param childMenu
     * @return
     */
    private boolean hasChild(List<SysMenuInfo> menuInfoList, SysMenuInfo childMenu) {
        return getChildList(menuInfoList, childMenu).size() > 0 ? true : false;
    }

    /**
     * 获取子节点列表
     * @param menuInfoList
     * @param menuInfo
     * @return
     */
    private List<SysMenuInfo> getChildList(List<SysMenuInfo> menuInfoList, SysMenuInfo menuInfo) {
        List<SysMenuInfo> childList = new ArrayList<>();
        Iterator<SysMenuInfo> iterator = menuInfoList.iterator();
        while (iterator.hasNext()) {
            SysMenuInfo nextMenu = iterator.next();
            if (nextMenu.getParentId().longValue() == menuInfo.getId().longValue()) {
                childList.add(nextMenu);
            }
        }
        return childList;
    }
}
